from time import sleep
from selenium.webdriver.common.by import By
from qturboframe.lib.webdriver.remote.webdriver import WebDriver
from qturboframe.lib.webdriver.exceptions import SeleniumError
from qturboframe.lib.report.log import logger

from qturboframe.public_ui.jresui2.checkbox import CheckBox
from qturboframe.public_ui.jresui2.form import Form
from qturboframe.public_ui.jresui2.input_type import InputType
from qturboframe.public_ui.jresui2.menu import Menu
from qturboframe.public_ui.jresui2.radio import Radio
from qturboframe.public_ui.jresui2.select import Select
from qturboframe.public_ui.jresui2.table import Table
from qturboframe.public_ui.jresui2.textarea import TextArea
from qturboframe.public_ui.jresui2.message import Message
from qturboframe.public_ui.jresui2.button import Button
from qturboframe.public_ui.jresui2.calendar import Calendar
from qturboframe.public_ui.jresui2.tree import Tree
from qturboframe.public_ui.jresui2.timer import Timer
from qturboframe.public_ui.jresui2.calendarm97 import CalendarM97
from qturboframe.public_ui.jresui2.frame import Frame
from qturboframe.public_ui.jresui2.tab import Tab
from qturboframe.public_ui.jresui2.datagrid_table import DataGridTable
from qturboframe.public_ui.jresui2.quote_table import QuoteTable


class FrontEnd(object):
    '''
    UI界面抽象类

    Attributes:
     - _driver: WebDriver
     - timeout: 默认的等待时间
    '''

    # <editor-fold desc="构造函数">
    def __init__(self, driver: WebDriver, timeout=3):
        self.driver = driver
        self.timeout = timeout

    # </editor-fold>

    # <editor-fold desc="获取控件对象">
    def input_type(self, idname=None, text=None, father=None):
        '''
        获取Jres2.0文本框对象

        :Args:
         - idname: 文本框的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}
         - father: 文本框的祖先级元素，可以给文本框查找限定范围，这样就不需要在整个页面中查找

        :Returns:
            hui的文本框对象

        :Example:
         - 例1: input_type = FrontEnd(driver).input_type(father=form)
         - 例2: input_type = FrontEnd(driver).input_type({By.ID:'id'})
         - 例3: input_type = FrontEnd(driver).input_type(text='请输入密码')
        '''
        if father is None:
            father = self.driver

        if text:
            return InputType(text, father, self.timeout)

        return InputType(idname, father, self.timeout)

    def button(self, idname=None, text=None, father=None, timeout=None):
        '''
        Jres2.0的按钮类，包括可点击的div

        :Args:
         - idname: 菜单栏的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}

        :Return:
            返回Menu对象

        :Example:
         - 例1: menu = FrontEnd(driver).menu()
         - 例2: menu = FrontEnd(driver).menu({By.ID:'id'})
         - 例3: menu = FrontEnd(driver).menu(text='导入')
        '''
        if father is None:
            father = self.driver

        if timeout is None:
            timeout = self.timeout

        if text:
            return Button(text, father, timeout)

        if idname:
            return Button(idname, father, timeout)

        return Button({By.CSS_SELECTOR: ".video-play"}, father, timeout)

    def textarea(self, idname, father=None):
        '''
        获取Jres2.0.0多行文本框对象

        :Args:
         - idname: 多行文本框的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}
         - father: 多行文本框的祖先级元素，可以给多行文本框查找限定范围，这样就不需要在整个页面中查找

        :Returns:
            hui的多行文本框对象

        :Example:
         - 例1: textarea = FrontEnd(driver).textarea(father=form)
         - 例2: textarea = FrontEnd(driver).textarea({By.ID:'id'})
        '''
        if father is None:
            father = self.driver
        return TextArea(idname, father, self.timeout)

    def select(self, idname, father=None):
        '''
        获取Jres2.0.0下拉框对象

        :Args:
         - idname: 下拉框的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}
         - father: 下拉框的祖先级元素，可以给下拉框查找限定范围，这样就不需要在整个页面中查找

        :Returns:
            hui的下拉框对象

        :Example:
         - 例1: select = FrontEnd(driver).select(father=form)
         - 例2: select = FrontEnd(driver).select({By.ID:'id'})
        '''
        if father is None:
            father = self.driver
        return Select(idname, father, self.timeout)

    def tab(self, idname=None, father=None):
        '''
        获取Jres2.0 tab对象

        :Args:
         - idname: tab的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}
         - father: tab的祖先级元素，可以给下拉框查找限定范围，这样就不需要在整个页面中查找

        :Returns:
            Jres2.0的下拉框对象

        :Example:
         - 例1: tab = FrontEnd(driver).tab(father=form)
         - 例2: tab = FrontEnd(driver).tab({By.ID:'id'})
        '''
        if father is None:
            father = self.driver

        if idname:
            return Tab(idname, father, self.timeout)

        return Tab({"css selector": ".h-screen-tab"}, father, self.timeout)

    def table(self, idname=None, father=None):
        '''
        获取Jres2.0.0 table

        :Args:
         - idname: 树形表格的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}
         - father: 树形表格的祖先级元素，可以给树形表格查找限定范围，这样就不需要在整个页面中查找

        :Returns:
            hui的树形表格对象

        :Example:
         - 例1: tree_table = FrontEnd(driver).tree_table(father=msg_box)
         - 例2: tree_table = FrontEnd(driver).tree_table({By.ID:'id'})
        '''
        if father is None:
            father = self.driver

        if idname:
            return Table(idname, father, self.timeout)

        return Table({"tag name": "table"}, father, self.timeout)

    def datagrid_table(self, idname=None, father=None):
        '''
        获取Jres2.0.0 table

        :Args:
         - idname: 树形表格的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}
         - father: 树形表格的祖先级元素，可以给树形表格查找限定范围，这样就不需要在整个页面中查找

        :Returns:
            hui的树形表格对象

        :Example:
         - 例1: tree_table = FrontEnd(driver).tree_table(father=msg_box)
         - 例2: tree_table = FrontEnd(driver).tree_table({By.ID:'id'})
        '''
        if father is None:
            father = self.driver

        if idname:
            return DataGridTable(idname, father, self.timeout)

        return DataGridTable({"tag name": "table"}, father, self.timeout)

    def quote_table(self, idname=None, father=None):
        '''
        获取Jres2.0.0 table， table的表头和表身在不同的table中

        :Args:
         - idname: 树形表格的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}
         - father: 树形表格的祖先级元素，可以给树形表格查找限定范围，这样就不需要在整个页面中查找

        :Returns:
            hui的树形表格对象

        :Example:
         - 例1: tree_table = FrontEnd(driver).tree_table(father=msg_box)
         - 例2: tree_table = FrontEnd(driver).tree_table({By.ID:'id'})
        '''
        if father is None:
            father = self.driver

        if idname:
            return QuoteTable(idname, father, self.timeout)

        return QuoteTable({"tag name": "table"}, father, self.timeout)

    def frame(self):
        '''
        获取Jres2.0.0 table

        :Args:
         - idname: 树形表格的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}
         - father: 树形表格的祖先级元素，可以给树形表格查找限定范围，这样就不需要在整个页面中查找

        :Returns:
            hui的树形表格对象

        :Example:
         - 例1: frame = FrontEnd(driver).frame()
        '''
        return Frame(self.driver, self.timeout)

    def form(self, idname=None, text=None, father=None):
        '''
        Jres2.0的form对象

        :Args:
         - element_para: 查找form的locator：{'css selector':'', 'text':'text'}
         - text: 表示form的文字

        :Return:
            返回form对象

        :Example:
         - 例1: form = FrontEnd(driver).form(text='结算记录信息')
         - 例2: form = FrontEnd(driver).form({By.ID:'id'})
        '''
        if father is None:
            father = self.driver

        if text:
            return Form(text, father, self.timeout)

        if idname:
            return Form(idname, father, self.timeout)

        return Form({"tag name": "form"}, father, self.timeout)

    def menu(self, idname=None):
        '''
        Jres2.0的菜单栏对象

        :Args:
         - idname: 菜单栏的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}

        :Return:
            返回Menu对象

        :Example:
         - 例1: menu = FrontEnd(driver).menu()
         - 例2: menu = FrontEnd(driver).menu({By.ID:'id'})
        '''
        if idname:
            menu = Menu(idname, self.driver, self.timeout)
        else:
            menu = Menu({By.TAG_NAME: 'body'}, self.driver, self.timeout)
        return menu

    def message(self, idname=None, text=None, timeout=3):
        '''
        获取Jires 2.0消息框对象

        :Args:
         - idname: 消息框的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}

        :Returns:
            hui的消息框对象

        :Example:
         - 例1: msg = FrontEnd(driver).message()
         - 例2: msg = FrontEnd(driver).message({By.ID:'id'})
        '''
        if idname:
            return Message(idname, self.driver, timeout)

        if text:
            return Message(text, self.driver, timeout)

        return Message({'xpath': ".//div[@class='m-message-positon']"}, self.driver, timeout)

    def calendar(self, idname=None, father=None, timeout=3):
        '''
        获取Jres2.0.0日历对象

        :Args:
         - idname: 消息框的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}

        :Returns:
            hui的日历对象

        :Example:
         - 例1: calendar = FrontEnd(driver).calendar()
         - 例2: calendar = FrontEnd(driver).calendar({By.ID:'id'})
         - 例3: calendar = FrontEnd(driver).calendar({"css selector":'css selector'})
        '''
        if not father:
            father = self.driver

        if idname:
            return Calendar(idname, self.driver, timeout)

        return Calendar({
                            'xpath': ".//div[contains(@class, 'dropdown-menu') and not(contains(@style,'display: none')) and not(contains(@class,'datetimepicker-dropdown-bottom'))]"},
                        self.driver, timeout)

    def calendarm97(self, idname, father=None, timeout=3):
        '''
        获取Jres2.0.0日历对象

        :Args:
         - idname: 消息框的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}

        :Returns:
            hui的日历对象

        :Example:
         - 例1: calendarm97 = FrontEnd(driver).calendarm97()
         - 例2: calendarm97 = FrontEnd(driver).calendarm97({By.ID:'id'})
         - 例3: calendarm97 = FrontEnd(driver).calendarm97({"css selector":'css selector'})
        '''
        if not father:
            father = self.driver
        return CalendarM97(idname, father, timeout)

    def checkbox(self, idname=None, father=None):
        '''
        获取Jres2.0.0复选框组对象

        :Args:
         - idname: 复选框组的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}
         - father: 复选框组的祖先级元素，可以给复选框组查找限定范围，这样就不需要在整个页面中查找

        :Returns:
            hui的复选框组对象

        :Example:
         - 例1: checkbox = FrontEnd(driver).checkbox(father=form)
         - 例2: checkbox = FrontEnd(driver).checkbox({By.ID:'id'})
         - 例3: checkbox = FrontEnd(driver).checkbox()
        '''
        if father is None:
            father = self.driver
        if idname:
            return CheckBox(idname, father, self.timeout)

        return CheckBox({'css selector': "input.h-checkbox-input,input[type='checkbox']"}, father, self.timeout)

    def radio(self, idname=None, father=None):
        '''
        获取Jres2.0.0单选按钮组对象

        :Args:
         - idname: 单选按钮组的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}
         - father: 单选按钮组的祖先级元素，可以给单选按钮组查找限定范围，这样就不需要在整个页面中查找

        :Returns:
            hui的单选按钮组对象

        :Example:
         - 例1: radioes = FrontEnd(driver).radioes(father=form)
         - 例2: radioes = FrontEnd(driver).radioes({By.ID:'id'})
        '''
        if father is None:
            father = self.driver
        if idname:
            radio = Radio(idname, father, self.timeout)
        else:
            radio = Radio({'css selector': "input[type='radio']"}, father, self.timeout)
        return radio

    def timer(self, idname=None, father=None):
        '''
        获取Jres2.0.0时间控件对象

        :Args:
         - idname: 时间控件的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}
         - father: 时间控件的祖先级元素，可以给时间控件查找限定范围，这样就不需要在整个页面中查找

        :Returns:
            hui的时间控件对象

        :Usage:
         - timer = FrontEnd(driver).timer(father=form)
         - timer = FrontEnd(driver).timer({By.ID:'id'})
        '''
        if father is None:
            father = self.driver
        if idname:
            timer = Timer(idname, father, self.timeout)
        else:
            timer = Timer({'css selector': 'div.h-date-picker'}, father, self.timeout)
        return timer

    def tree(self, idname=None, father=None, timeout=3):
        '''
        获取Jres2.0.0 tree对象

        :Args:
         - idname: 消息框的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}

        :Returns:
            hui的消息框对象

        :Example:
         - 例1: msg = FrontEnd(driver).message()
         - 例2: msg = FrontEnd(driver).message({By.ID:'id'})
        '''
        if not father:
            father = self.driver

        if idname:
            return Tree(idname, father, timeout)

        return Tree({'css selector': "div.u-ztree"}, father, timeout)

    # </editor-fold>


